package com.imooc.service.impl;

import com.github.pagehelper.PageInfo;
import com.imooc.es.pojo.Items;
import com.imooc.es.pojo.Stu;
import com.imooc.service.ItemsESService;
import com.imooc.utils.PagedGridResult;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author gcq
 * @Create 2022-04-09
 */
@Service
public class ItemsServiceImpl implements ItemsESService {

    @Autowired
    private ElasticsearchTemplate esTemplate;

    @Override
    public PagedGridResult searchItems(String keywords,
                                       String sort,
                                       Integer page,
                                       Integer pageSize) {
        PageRequest pageable = PageRequest.of(page, pageSize);
//        String preTag = "<font color='red'>";
//        String postTag = "</font>";

        // 支持多个排序
        FieldSortBuilder sortBuffer = null;
        if(sort.equals("c")) {
            sortBuffer = new FieldSortBuilder("sellCounts")
                    .order(SortOrder.DESC);
        } else if(sort.equals("p")) {
            sortBuffer = new FieldSortBuilder("price")
                    .order(SortOrder.DESC);
        } else {
            sortBuffer = new FieldSortBuilder("itemName.keyword")
                    .order(SortOrder.DESC);
        }

        String itemNameField = "itemName";

        SearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery(itemNameField, keywords))
                .withHighlightFields(new HighlightBuilder.Field(itemNameField)
//                        .preTags(preTag)
//                        .postTags(postTag)
                        )
                .withSort(sortBuffer)
                .withPageable(pageable)
                .build();

        AggregatedPage<Items> pageItems = esTemplate.queryForPage(query, Items.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
                List<Items> itemsHighlightList = new ArrayList<>();

                SearchHits hits = response.getHits();
                for (SearchHit h : hits) {
                    HighlightField highlightField = h.getHighlightFields().get(itemNameField);
                    String itemName = highlightField.getFragments()[0].toString();
                    Map<String, Object> sourceAsMap = h.getSourceAsMap();

                    Object itemId = (Object) sourceAsMap.get("itemId");
                    String imgUrl = (String) sourceAsMap.get("imgUrl");
                    Object price = (Object) sourceAsMap.get("price");
                    Object sellCounts = (Object) sourceAsMap.get("sellCounts");

                    Items items = new Items();
                    items.setItemId(itemId.toString());
                    items.setItemName(itemName);
                    items.setImgUrl(imgUrl);
                    items.setPrice(Integer.valueOf(price.toString()));
                    items.setSellCounts(Integer.valueOf(sellCounts.toString()));

                    itemsHighlightList.add(items);
                }
                return new AggregatedPageImpl<>((List<T>) itemsHighlightList,
                        pageable,
                        response.getHits().totalHits);
            }
        });

        return PagedGridResult.getPageResult(pageItems.getContent(), page);
    }
}